// Keywords: nonWF, non-Wright-Fisher, continuous space, continuous spatial landscape, periodic boundaries, selfing

initialize() {
	initializeSLiMModelType("nonWF");
	initializeSLiMOptions(dimensionality="xy", periodicity="xy");
	defineConstant("K", 300);   // carrying capacity
	defineConstant("S", 0.1);   // spatial competition distance
	
	initializeMutationType("m1", 0.5, "f", 0.0);
	m1.convertToSubstitution = T;
	
	initializeGenomicElementType("g1", m1, 1.0);
	initializeGenomicElement(g1, 0, 99999);
	initializeMutationRate(1e-7);
	initializeRecombinationRate(1e-8);
	
	// spatial competition
	initializeInteractionType(1, "xy", reciprocal=T, maxDistance=S);
	
	// spatial mate choice
	initializeInteractionType(2, "xy", reciprocal=T, maxDistance=0.1);
}
2: first() {
	// look for mates
	i2.evaluate(p1);
}
reproduction() {
	// choose our nearest neighbor as a mate, within the max distance
	mate = i2.nearestNeighbors(individual, 1);
	
	for (i in seqLen(rpois(1, 0.1)))
	{
		if (mate.size())
			offspring = subpop.addCrossed(individual, mate);
		else
			offspring = subpop.addSelfed(individual);
		
		// set offspring position
		pos = individual.spatialPosition + rnorm(2, 0, 0.02);
		offspring.setSpatialPosition(p1.pointPeriodic(pos));
	}
}
1 early() {
	sim.addSubpop("p1", 1);
	
	// random initial positions
	p1.individuals.setSpatialPosition(p1.pointUniform(1));
}
early() {
	i1.evaluate(p1);
	
	// spatial competition provides density-dependent selection
	inds = p1.individuals;
	competition = i1.totalOfNeighborStrengths(inds);
	competition = (competition + 1) / (PI * S^2);
	inds.fitnessScaling = K / competition;
}
late()
{
	// move around a bit
	for (ind in p1.individuals)
	{
		newPos = ind.spatialPosition + runif(2, -0.01, 0.01);
		ind.setSpatialPosition(p1.pointPeriodic(newPos));
	}
}
10000 late() {
	sim.outputFixedMutations();
}
